import axios, { AxiosInstance } from 'axios';

// Types aligned with backend OpenAPI contract
export interface CategoryDict {
  code: string;
  name: string;
  definition?: string;
  keywords?: string[];
  is_active?: 0 | 1;
}

export interface CategoryStat {
  code: string;
  name: string;
  count: number;
  ratio: number;
}

export interface TaskStatus {
  id?: number;
  version?: number;
  status?: string;
  total?: number;
  processed?: number;
  success?: number;
  failed?: number;
  started_at?: string;
  finished_at?: string;
}

export interface RunClassifyResponse {
  taskId: number;
  version: number;
  status: string;
}

export interface TopExampleItem {
  snMasked: string;
  backDetail: string;
}

export const getBaseURL = () => {
  const env = process.env.NEXT_PUBLIC_API_BASE_URL;
  if (typeof window !== 'undefined') {
    if (!env || env === 'auto' || env === 'same-origin') {
      return '';
    }
  }
  return env?.replace(/\/$/, '') || 'http://localhost:8080';
};

let client: AxiosInstance | null = null;

function getApiTimeoutMs(): number {
  const raw = process.env.NEXT_PUBLIC_API_TIMEOUT_MS;
  if (!raw) return 600000; // default 10 minutes
  const s = String(raw).trim().toLowerCase();
  try {
    if (s.endsWith('ms')) return Math.max(0, parseInt(s.slice(0, -2)));
    if (s.endsWith('s')) return Math.max(0, Math.floor(parseFloat(s.slice(0, -1)) * 1000));
    if (s.endsWith('m')) return Math.max(0, Math.floor(parseFloat(s.slice(0, -1)) * 60_000));
    const n = parseInt(s, 10);
    return Number.isFinite(n) ? Math.max(0, n) : 600000;
  } catch {
    return 600000;
  }
}

function getToken(): string | null {
  if (typeof window === 'undefined') return null;
  // try common keys
  return (
    localStorage.getItem('JWT') ||
    localStorage.getItem('jwt') ||
    localStorage.getItem('token') ||
    null
  );
}

export function apiClient(): AxiosInstance {
  if (client) return client;
  client = axios.create({
    baseURL: getBaseURL(),
    headers: {
      'Content-Type': 'application/json',
    },
    withCredentials: false,
    timeout: getApiTimeoutMs(),
  });

  client.interceptors.request.use((config) => {
    const token = getToken();
    if (token) {
      config.headers = config.headers || {};
      (config.headers as any)['Authorization'] = `Bearer ${token}`;
    }
    return config;
  });

  return client;
}

// API methods
export async function getStats(params: {
  taskVersion?: number;
  dateFrom?: string;
  dateTo?: string;
} = {}): Promise<CategoryStat[]> {
  const { data } = await apiClient().get<CategoryStat[]>('/api/stats', { params });
  return data;
}

export async function getCategories(): Promise<CategoryDict[]> {
  const { data } = await apiClient().get<CategoryDict[]>('/api/categories');
  return data;
}

export async function getTopExamples(code: string, limit = 3): Promise<TopExampleItem[]> {
  const { data } = await apiClient().get<TopExampleItem[]>(
    '/api/stats/top-examples',
    { params: { code, limit } },
  );
  return data;
}

export async function runClassify(params: {
  batchSize?: number;
  maxConcurrency?: number;
  taskVersion?: number;
}): Promise<RunClassifyResponse> {
  const { data } = await apiClient().post<RunClassifyResponse>(
    '/api/classify/run',
    null,
    { params },
  );
  return data;
}

export function getTaskUrl(taskId: number | string): string {
  return `${getBaseURL()}/api/classify/task/${taskId}`;
}

// Build taxonomy (category induction)
export interface BuildResponse {
  inserted: number;
  preview: CategoryDict[];
}

export async function buildTaxonomy(sampleSize?: number): Promise<BuildResponse> {
  const { data } = await apiClient().post<BuildResponse>(
    '/api/taxonomy/build',
    null,
    { params: sampleSize ? { sampleSize } : undefined },
  );
  return data;
}

// Approve taxonomy candidates
export async function approveTaxonomy(items: CategoryDict[]): Promise<void> {
  await apiClient().post('/api/taxonomy/approve', items);
}

// List available classify versions
export async function getVersions(): Promise<number[]> {
  const { data } = await apiClient().get<number[]>('/api/classify/versions');
  return data;
}
